/*
 * Copyright (c) 2010 Curtis Boyden.  All rights reserved. 
 * This software was developed by Curtis Boyden and is provided under the terms 
 * of the GNU Lesser General Public License, Version 2.1. You may not use 
 * this file except in compliance with the license. If you need a copy of the license, 
 * please go to http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is ejMud
 * (Ewerp Java MUD).  The Initial Developer is Curtis Boyden.
 *
 * Software distributed under the GNU Lesser Public License is distributed on an "AS IS" 
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to 
 * the license for the specific language governing your rights and limitations.
*/

package com.ewerp.mud.commands;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.ewerp.mud.core.EwerpProperties;
import com.ewerp.mud.core.exceptions.EwerpMudException;

public class EwerpCommandRegistry implements ICommandRegistry {

	private static EwerpCommandRegistry instance = null;
	private static Boolean initialized = false;
	
	protected List<ICommandEntry> commandList = new ArrayList<ICommandEntry>();
	
	private EwerpCommandRegistry() {
	}
	
	protected void load(String commandRegistryFile) {
		try {
			Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(commandRegistryFile));
			XPath xPath = XPathFactory.newInstance().newXPath();
			NodeList commandNodes = (NodeList) xPath.evaluate("//command", doc, XPathConstants.NODESET);
			
			for(int i = 0; i < commandNodes.getLength(); i++) {
				Node commandNode = commandNodes.item(i);

				ICommandEntry commandEntry = new ICommandEntry() {
					private List<String> commandAliasList = new ArrayList<String>();
					private Map<String, String> commandParserMap = new HashMap<String, String>();

					@Override
					public List<String> getCommandAliasList() {
						return commandAliasList;
					}

					@Override
					public Map<String, String> getCommandParserMap() {
						return commandParserMap;
					}
				};

				// Get command class
//				commandNode.getAttributes().getNamedItem("class").getTextContent();
				
				NodeList commandDetailNodes = commandNode.getChildNodes();
				
				for(int c = 0; c < commandDetailNodes.getLength(); c++) {
					Node commandDetailNode = commandDetailNodes.item(c);
					
					if(commandDetailNode.getNodeName().equalsIgnoreCase("alias")) {
						// Get a command alias
						commandEntry.getCommandAliasList().add(commandDetailNode.getTextContent());
					} else if(commandDetailNode.getNodeName().equalsIgnoreCase("parser")) {
						// Get a command parser
						commandEntry.getCommandParserMap().put(commandDetailNode.getAttributes().getNamedItem("class").getTextContent(), commandDetailNode.getTextContent());
					}
				}
				
				commandList.add(commandEntry);
			}
			
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static EwerpCommandRegistry getInstance() {
		synchronized(initialized) {
			if(!initialized) {
				instance = new EwerpCommandRegistry();
				try {
					instance.load(EwerpProperties.getInstance().getProperty("file.command-registry"));
					initialized = true;
				} catch (EwerpMudException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					instance = null;
				}
			}
		}
		
		return instance;
	}

	@Override
	public List<ICommandEntry> getCommandList() {
		synchronized(initialized) {
			return commandList;
		}
	}

}
